Crate path_abs

Source
Expand description

Ergonomic paths and files in rust.

This library aims to provide ergonomic path and file operations to rust with reasonable performance.

This includes:

  • Improved methods for the std path types using PathInfo PathMut and PathOps
  • Cleaner absolute paths (which is distinct from canonicalized paths).
  • Improved error messages, see the Better Errors section.
  • Improved type safety. The types specify that a file/dir once existed and was once a certain type. Obviously a file/dir can be deleted/changed by another process.
  • More stringent mutability requirements. See the Differing Method Signatures section.
  • Cheap cloning: all path types are Arc, which a cheap operation compared to filesystem operations and allows more flexibility and ergonomics in the library for relatively low cost.

§Better Errors

All errors include the path and action which caused the error, as well as the unaltered std::io::Error message. Errors are convertable into std::io::Error, giving almost complete compatibility with existing code.

§set_len (i.e. truncate a file):

The above error is actually impossible because FileWrite is always writeable, and FileRead does not implement set_len. However, it is kept for demonstration.

§open_read (open file for reading):

And every other method has similarily improved errors. If a method does not have pretty error messages please open a ticket.

§Exported Path Types

These are the exported Path types. All of them are absolute.

  • PathAbs: a reference counted absolute (not necessarily canonicalized) path that is not necessarily guaranteed to exist.
  • PathFile: a PathAbs that is guaranteed (at instantiation) to exist and be a file, with associated methods.
  • PathDir: a PathAbs that is guaranteed (at instantiation) to exist and be a directory, with associated methods.
  • PathType: an enum containing either a PathFile or a PathDir. Returned by PathDir::list

In addition, all paths are serializable through serde (even on windows!) by using the crate stfu8 to encode/decode, allowing ill-formed UTF-16. See that crate for more details on how the resulting encoding can be edited (by hand) even in the case of what would be ill-formed UTF-16.

§Exported File Types

All File types provide type safe access to their relevant traits. For instance, you can’t read with a FileWrite and you can’t write with a FileRead.

  • FileRead: a read-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a read-only file.
  • FileWrite: a write-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a write-only file.
  • FileEdit: a read/write file handle with path() attached and improved error messages. Contains methods and trait implements for both readable and writeable files.

§Differing Method Signatures

The type signatures of the File* types regarding read, write and other methods is slightly different than std::fs::File – they all take &mut instead of &. This is to avoid a common possible footgun.

To demonstrate, imagine the following scenario:

  • You pass your open &File to a method, which puts it in a thread. This thread constantly calls seek(SeekFrom::Start(10))
  • You periodically read from a file expecting new data, but are always getting the same data.

Yes, this is actually allowed by the rust compiler since seek is implemented for &File. Technically this is still memory safe since the operating system will handle any contention, however many would argue that it isn’t expected that an immutable reference passed to another function can affect the seek position of a file.

§Examples

Recreating Cargo.init in example/

use std::path::Path;
use std::collections::HashSet;
use path_abs::{
    PathAbs,   // absolute path
    PathDir,   // absolute path to a directory
    PathFile,  // absolute path to a file
    PathType,  // enum of Dir or File
    PathInfo,  // trait for query methods
    PathOps,   // trait for methods that make new paths
    FileRead,  // Open read-only file handler
    FileWrite, // Open write-only file handler
    FileEdit,  // Open read/write file handler
};

let example = Path::new("example");

// Create your paths
let project = PathDir::create_all(example)?;
let src = PathDir::create(project.concat("src")?)?;
let lib = PathFile::create(src.concat("lib.rs")?)?;
let cargo = PathFile::create(project.concat("Cargo.toml")?)?;

// Write the templates
lib.write_str(r#"
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}"#)?;

cargo.write_str(r#"
[package]
name = "example"
version = "0.1.0"
authors = ["Garrett Berg <vitiral@gmail.com>"]

[dependencies]
"#)?;

// Put our result into a HashMap so we can assert it
let mut result = HashSet::new();
for p in project.list()? {
    result.insert(p?);
}

// Create our expected value
let mut expected = HashSet::new();
expected.insert(PathType::Dir(src));
expected.insert(PathType::File(cargo));

assert_eq!(expected, result);

// ----------------------------------
// Creating types from existing paths

// Creating a generic path
let lib_path = example.join("src").join("lib.rs");
let abs = PathAbs::new(&lib_path)?;

// Or a path with a known type
let file = PathType::new(&lib_path)
    ?
    .unwrap_file();

assert!(abs.is_file());
assert!(file.is_file());

// ----------------------------------
// Opening a File

// open read-only using the PathFile method
let read = file.open_read()?;

// Or use the type directly: open for appending
let write = FileWrite::open_append(&file)?;

// Open for read/write editing.
let edit = file.open_edit()?;

Re-exports§

Modules§

  • Open file paths and associated methods.

Structs§

  • An error produced by performing an filesystem operation on a Path.
  • A read/write file handle with path() attached and improved error messages. Contains methods and trait implements for both readable and writeable files.
  • A read-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a read-only file.
  • A write-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a write-only file.
  • An iterator over PathType objects, returned by PathDir::list.
  • An absolute (not necessarily canonicalized) path that may or may not exist.
  • A PathAbs that is guaranteed to be a directory, with associated methods.
  • a PathAbs that was a file at the time of initialization, with associated methods.

Enums§

  • An an enum containing either a file or a directory.

Traits§

  • Methods that return information about a path.
  • Methods that modify a path.
  • Methods that return new path-like objects.

Type Aliases§